package com.abigdreamer.swing.app;

import com.abigdreamer.swing.EmptyComponent;
import com.abigdreamer.swing.app.skin.SkinConst;
import com.abigdreamer.swing.component.JCLabel;
import com.abigdreamer.swing.component.UIUtil;
import com.abigdreamer.util.FileUtil;
import craky.component.JImagePane;
import craky.componentc.JCCheckBox;
import craky.componentc.JCComboBox;
import craky.componentc.JCLimitedPassword;
import craky.componentc.JCMessageBox;
import craky.layout.LineLayout;
import craky.security.Checker;
import craky.util.Config;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ComboBoxEditor;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;

public class LoginWindow
  extends ActionFrame
{
  private static final long serialVersionUID = -3144576417706510085L;
  private JCComboBox comboUser;
  private JCLimitedPassword txtPsd;
  private JCCheckBox cbSavePsd;
  private JCCheckBox cbAuto;
  private JCLabel lbDelUserInfo;
  private JCLabel lbModifyPsd;
  private boolean godReleased;
  private static String bannerName;
  public static final String FILE_SEP = System.getProperty("file.separator");
  public static final String BANNER_DIR = SkinConst.IMAGE_DIR + FILE_SEP + "banner";
  public static final int MAX_PASSWORD_LENGTH = 100;
  protected EmptyComponent ecStatus;
  public static final String NAME_UNALLOWED = "非法用户名！";
  public static final String USER_NOT_EXIST = "该用户不存在！";
  
  public static String getBannerName()
  {
    if (bannerName == null) {
      bannerName = FileUtil.getRandomEndsWithFileName(BANNER_DIR, ".png");
    }
    return bannerName;
  }
  
  public LoginWindow(String title, String logo, int width, int height)
  {
    super(title, logo, width, height);
    
    setAlwaysOnTop(true);
    
    pack();
    setLocationRelativeTo(null);
  }
  
  public void setVisible(boolean v)
  {
    initBanner();
    initHistory();
    super.setVisible(v);
  }
  
  protected void onButtonOKClick()
  {
    onLogin(getSelectedUserName(), this.txtPsd.getPassword());
  }
  
  protected void onLogin(String userName, char[] cs) {}
  
  protected void onButtonCancleClick()
  {
    System.exit(0);
  }
  
  protected void initCenterPane()
  {
    ItemHandler itemListener = new ItemHandler();
    EditHandler editListener = new EditHandler();
    
    JCLabel lbUser = createLabel("用户名：");
    JCLabel lbPsd = createLabel("密　码：");
    
    this.lbDelUserInfo = createLinkedLabel("删除记录");
    this.lbModifyPsd = createLinkedLabel("修改密码");
    
    this.comboUser = new JCComboBox();
    this.comboUser.setPreferredSize(new Dimension(-1, 26));
    this.comboUser.setEditable(true);
    ((JTextComponent)this.comboUser.getEditor().getEditorComponent()).getDocument().addDocumentListener(editListener);
    
    this.txtPsd = new JCLimitedPassword(100);
    this.txtPsd.setPreferredSize(this.comboUser.getPreferredSize());
    
    this.cbSavePsd = new JCCheckBox("记住密码");
    this.cbSavePsd.addItemListener(itemListener);
    
    this.cbAuto = new JCCheckBox("自动登陆");
    this.cbAuto.addItemListener(itemListener);
    
    EmptyComponent ecUser = new EmptyComponent();
    ecUser.setLayout(new LineLayout(0, 0, 0, 14, 0, 0, 10, 0));
    ecUser.setPreferredSize(new Dimension(-1, 50));
    ecUser.add(lbUser, "Start");
    ecUser.add(this.comboUser, "Middle");
    ecUser.add(this.lbDelUserInfo, "End");
    
    EmptyComponent ecPsd = new EmptyComponent();
    ecPsd.setLayout(new LineLayout(0, 0, 0, 0, 0, 0, 10, 0));
    ecPsd.setPreferredSize(new Dimension(-1, 30));
    ecPsd.add(lbPsd, "Start");
    ecPsd.add(this.txtPsd, "Middle");
    ecPsd.add(this.lbModifyPsd, "End");
    
    this.ecStatus = new EmptyComponent();
    this.ecStatus.setLayout(new LineLayout(12, 105, 0, 0, 0, 10, 10, 0));
    this.ecStatus.setPreferredSize(new Dimension(-1, 27));
    this.ecStatus.add(this.cbSavePsd, "End");
    this.ecStatus.add(this.cbAuto, "End");
    
    this.centerPane.add(ecUser, "StartFill");
    this.centerPane.add(ecPsd, "StartFill");
    this.centerPane.add(this.ecStatus, "EedFill");
    
    this.bannerPane.addMouseListener(new MouseAdapter()
    {
      public void mouseReleased(MouseEvent e)
      {
        LoginWindow.this.godReleased = ((e.getSource() == LoginWindow.this.bannerPane) && (e.isAltDown()) && (e.getClickCount() == 3) && (SwingUtilities.isRightMouseButton(e)));
      }
    });
    UIUtil.actionLabel(this.lbDelUserInfo, new AbstractAction()
    {
      private static final long serialVersionUID = 1314650981076868723L;
      
      public void actionPerformed(ActionEvent e)
      {
        LoginWindow.this.deleteUserInfo();
      }
    });
    UIUtil.actionLabel(this.lbModifyPsd, new AbstractAction()
    {
      private static final long serialVersionUID = -8098585019722294097L;
      
      public void actionPerformed(ActionEvent e)
      {
        LoginWindow.this.modifyPassword();
      }
    });
  }
  
  private void initBanner()
  {
    Image img = getBannerImage();
    if (img != null) {
      this.bannerPane.setImage(img);
    }
  }
  
  protected Image getBannerImage()
  {
    String bannerName = getBannerName();
    if (bannerName != null) {
      return new ImageIcon(BANNER_DIR + FILE_SEP + bannerName).getImage();
    }
    return null;
  }
  
  protected List<String> getLoginHistory()
  {
    return LoginConfigMgr.getLoginHistory();
  }
  
  protected void onDeleteUser(String name)
  {
    LoginConfigMgr.removeHistoryUser(name);
  }
  
  protected String getSavedPassword(String name)
  {
    return LoginConfigMgr.getLoginConfig().getProperty(name + ".password");
  }
  
  protected boolean checkIsAutoLogin(String name)
  {
    return Boolean.parseBoolean(LoginConfigMgr.getLoginConfig().getProperty(name + ".auto", "false"));
  }
  
  private void initHistory()
  {
    List<String> history = getLoginHistory();
    if ((history != null) && (!history.isEmpty()))
    {
      for (String name : history) {
        this.comboUser.addItem(name);
      }
      this.comboUser.setSelectedIndex(0);
      requestPassword(false);
    }
    else
    {
      requestUser();
    }
  }
  
  public void requestUser()
  {
    this.comboUser.requestFocus();
  }
  
  public void requestPassword(boolean clear)
  {
    if (clear) {
      clearPassword();
    }
    this.txtPsd.requestFocus();
  }
  
  public void clearPassword()
  {
    this.txtPsd.setText("");
  }
  
  public boolean isSavePassword()
  {
    return this.cbSavePsd.isSelected();
  }
  
  private void setSavePassword(boolean save)
  {
    this.cbSavePsd.setSelected(save);
  }
  
  public boolean isAutoLogin()
  {
    return this.cbAuto.isSelected();
  }
  
  private void setAutoLogin(boolean auto)
  {
    this.cbAuto.setSelected(auto);
  }
  
  private String getSelectedUserName()
  {
    return ((JTextComponent)this.comboUser.getEditor().getEditorComponent()).getText();
  }
  
  private void deleteUserInfo()
  {
    String name = getSelectedUserName();
    
    onDeleteUser(name);
    
    this.comboUser.removeItem(name);
    if (this.comboUser.getItemCount() > 0) {
      this.comboUser.setSelectedIndex(0);
    } else {
      ((JTextComponent)this.comboUser.getEditor().getEditorComponent()).setText(null);
    }
  }
  
  public static boolean isAllowedName(String name)
  {
    return (name != null) && (!(name = name.trim()).isEmpty()) && (name.indexOf(',') < 0);
  }
  
  protected boolean checkUserExist(String name)
  {
    return false;
  }
  
  private void modifyPassword()
  {
    String name = getSelectedUserName();
    String failInfo = null;
    if (!isAllowedName(name)) {
      failInfo = "非法用户名！";
    }
    if (!checkUserExist(name)) {
      failInfo = "该用户不存在！";
    }
    if (failInfo != null)
    {
      JCMessageBox box = JCMessageBox.createErrorMessageBox(this, "修改密码", failInfo);
      Image image = new ImageIcon(LoginConfigMgr.BANNER_BG_DIR + LoginConfigMgr.FILE_SEP + bannerName).getImage();
      box.setBackgroundImage(image);
      box.open();
      requestUser();
    }
    else
    {
      try
      {
        openUserInfoDialog(bannerName, this, name);
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
    }
  }
  
  protected void openUserInfoDialog(String bannerName, LoginWindow loginWindow, String userName) {}
  
  public boolean isGodReleased()
  {
    return this.godReleased;
  }
  
  public static String getPasswordTextWhenSaved(String savedPassword)
  {
    return Long.toHexString(Checker.compute(savedPassword, "CRC-32"));
  }
  
  private class ItemHandler
    implements ItemListener
  {
    private ItemHandler() {}
    
    public void itemStateChanged(ItemEvent e)
    {
      Object source = e.getSource();
      int state = e.getStateChange();
      if (source == LoginWindow.this.cbSavePsd)
      {
        String name = LoginWindow.this.getSelectedUserName();
        String savedPassword = null;
        if (state == 2)
        {
          if (LoginWindow.this.cbAuto.isSelected()) {
            LoginWindow.this.cbAuto.setSelected(false);
          }
        }
        else if ((savedPassword = LoginWindow.this.getSavedPassword(name)) != null) {
          LoginWindow.this.txtPsd.setText(LoginWindow.getPasswordTextWhenSaved(savedPassword));
        }
      }
      else if ((source == LoginWindow.this.cbAuto) && (state == 1) && (!LoginWindow.this.cbSavePsd.isSelected()))
      {
        LoginWindow.this.cbSavePsd.setSelected(true);
      }
    }
  }
  
  private class EditHandler
    implements DocumentListener
  {
    private EditHandler() {}
    
    public void insertUpdate(DocumentEvent e)
    {
      checkState(e);
    }
    
    public void removeUpdate(DocumentEvent e)
    {
      checkState(e);
    }
    
    public void changedUpdate(DocumentEvent e)
    {
      checkState(e);
    }
    
    private void checkState(DocumentEvent e)
    {
      String name = LoginWindow.this.getSelectedUserName();
      if (LoginWindow.this.getLoginHistory().contains(name))
      {
        LoginWindow.this.setAutoLogin(LoginWindow.this.checkIsAutoLogin(name));
        LoginWindow.this.setSavePassword(LoginWindow.this.getSavedPassword(name) != null);
      }
      else
      {
        LoginWindow.this.setSavePassword(false);
        LoginWindow.this.setAutoLogin(false);
      }
      if (!LoginWindow.this.isSavePassword()) {
        LoginWindow.this.clearPassword();
      }
    }
  }
}
